/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dao;

import java.util.ArrayList;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import pojo.Foreignkey;
import pojo.Property;

/**
 *
 * @author HoangLiem
 */
public class ExecPropertyXML {

    /*
     * Add 1 property vào table
     */
    public static boolean addPropertyToTable(Document doc, String nameTable, Property pt) {
        boolean result = true;
        if (ExecTableXML.isExistedFieldName(doc, nameTable, pt.getName())) {
            return result = false;
        }
        try {
            doc.getDocumentElement().normalize();
            NodeList nl = doc.getElementsByTagName("table");
            Node node = null;
            Element table = null;
            for (int i = 0; i < nl.getLength(); i++) {
                node = nl.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    table = (Element) node;
                    if (table.getAttribute("name").equalsIgnoreCase(nameTable)) {
                        Element property = doc.createElement("property");
                        property.setAttribute("name", pt.getName().toString().toLowerCase());
                        property.setAttribute("type", pt.getType().toString().toLowerCase());
                        property.setAttribute("length", Integer.toString(pt.getLength()).toLowerCase());
                        property.setAttribute("notnull", ExecTableXML.convertNotnull(pt).toLowerCase());
                        property.setAttribute("unique", ExecTableXML.convertUnique(pt).toLowerCase());

                        //Them node theo dung vi tri
                        Node fkNode = ExecXML.getFirstNodeByNodeName(doc, nameTable, "foreignkey");
                        Node rowNode = ExecXML.getFirstNodeByNodeName(doc, nameTable, "row");
                        if (fkNode != null) {
                            table.insertBefore(property, fkNode);
                            table.insertBefore(doc.createTextNode("\n\t\t"), fkNode);
                        } else {
                            if (rowNode != null) {
                                table.insertBefore(property, rowNode);
                                table.insertBefore(doc.createTextNode("\n\t\t"), rowNode);
                            } else {
                                if (table.hasChildNodes()) {
                                    table.appendChild(doc.createTextNode("\t"));
                                } else {
                                    table.appendChild(doc.createTextNode("\n\t"));
                                }
                                table.appendChild(property);
                                table.appendChild(doc.createTextNode("\n\t"));
                            }
                        }
                    }
                }
            }
            ExecRowXML.insertAttributeOfRow(doc, nameTable, pt.getName());
            ExecXML.saveXmlFile(doc, ExecTableXML.getNameDatabase(doc) + ".xml");
            // }
        } catch (Exception e) {
            result = false;
            e.printStackTrace();
        }
        return result;
    }
    /*
     *  Hàm này lấy các Property của 1 table
     */

    public static ArrayList<Property> getPropertyOfTable(Document doc, String tableName) {
        ArrayList<Property> Properties = new ArrayList<Property>();
        try {
            doc.getDocumentElement().normalize();
            NodeList nl = doc.getElementsByTagName("property");
            Node node = null;
            Element pt = null;
            for (int i = 0; i < nl.getLength(); i++) {
                node = nl.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    pt = (Element) node;
                    Property temp = new Property();
                    Element pr = (Element) pt.getParentNode();
                    if (pr.getAttribute("name").equalsIgnoreCase(tableName)) {
                        temp.setName(pt.getAttribute("name"));
                        temp.setLength(Integer.parseInt(pt.getAttribute("length")));
                        temp.setType(pt.getAttribute("type"));
                        temp.setNotnull(ExecTableXML.convertElementNotnull(pt));
                        temp.setUnique(ExecTableXML.convertElementUnique(pt));
                        Properties.add(temp);
                    }
                }
            }
            if (Properties.isEmpty()) {
                Properties = null;
            }

        } catch (Exception e) {
            Properties = null;
            e.printStackTrace();
        }
        return Properties;
    }

    /*
     *  Hàm này lấy 1 Property của 1 table theo thuộc tính name của property
     */
    public static Property getPropertyOfTable(Document doc, String tableName, String nameProperty) {
        Property property = new Property();
        try {
            doc.getDocumentElement().normalize();
            NodeList nl = doc.getElementsByTagName("property");
            Node node = null;
            Element pt = null;
            for (int i = 0; i < nl.getLength(); i++) {
                node = nl.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    pt = (Element) node;
                    Property temp = new Property();
                    Element pr = (Element) pt.getParentNode();
                    if (pr.getAttribute("name").equalsIgnoreCase(tableName) && pt.getAttribute("name").equalsIgnoreCase(nameProperty)) {
                        property.setName(pt.getAttribute("name"));
                        property.setLength(Integer.parseInt(pt.getAttribute("length")));
                        property.setType(pt.getAttribute("type"));
                        property.setNotnull(ExecTableXML.convertElementNotnull(pt));
                        property.setUnique(ExecTableXML.convertElementUnique(pt));
                    }
                }
            }

        } catch (Exception e) {
            //property = null;
            e.printStackTrace();
        }
        return property;
    }

    public static Property getPropertyOfTable(String databaseName, String tableName, String nameProperty) {
        try {
            databaseName = databaseName.trim();
            tableName = tableName.trim();
            nameProperty = nameProperty.trim();
            Document doc = ExecXML.getDocument(databaseName + ".xml");
            return getPropertyOfTable(doc, tableName, nameProperty);
        } catch (Exception ex) {
            return null;
        }
    }

    /*
     * Ham nay kiem tra 1 ten property co ton tai chua, lưu ý lay tat ca tên id và thuộc tính
     */
    public static boolean isExistedProperty(Document doc, String tableName, String PropertyName) {
        try {
            ArrayList<Property> pro = getPropertyOfTable(doc, tableName);
            ArrayList<String> proName = new ArrayList<String>();
            if (pro != null && !pro.isEmpty()) {
                for (int i = 0; i < pro.size(); i++) {
                    proName.add(pro.get(i).getName().toString().toLowerCase());
                }
            } else {
                return false;
            }
            return ExecXML.isExistedString(proName, PropertyName.toLowerCase());
        } catch (Exception ex) {
            return true;
        }
    }

    /*
     * Hàm này lấy về vị trí 1 thuộc tính bất kỳ trong table, 
     * lưu ý vị trí có ý nghĩa về mặt logic
     * có nghĩa là ta quan tâm vị trí nó trong danh sách các thuộc tính( thẻ id, thẻ property)
     * Vì trong table các thẻ id, property, foreignkey năm xen kẽ lẫn nhau
     */
    public static int getActualPosition(Document doc, String tableName, String propertyName) {
        int pos = -1;
        try {
            String xPath = "database/table[translate(@name,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='" + tableName.toLowerCase() + "']";
            Node table = (Node) ExecXML.execXpathReturnNode(doc, xPath);
            if (table != null && table.hasChildNodes()) {
                NodeList nodeList = table.getChildNodes();
                int proPos = -1;
                for (int i = 0; i < nodeList.getLength(); i++) {
                    Node node = nodeList.item(i);
                    if (node.getNodeType() == Node.ELEMENT_NODE) {
                        if (node.getNodeName().equalsIgnoreCase("id") || node.getNodeName().equalsIgnoreCase("property")) {
                            Element ele = (Element) node;
                            proPos++;
                            if (ele.getAttribute("name").equalsIgnoreCase(propertyName)) {
                                pos = proPos;
                            }
                        }
                    }
                }
            } else {
                pos = -1;
            }
        } catch (Exception ex) {
            pos = -1;
        }
        return pos;
    }

    public static int getActualPosition(String databaseName, String tableName, String propertyName) {
        try {
            databaseName = databaseName.trim();
            tableName = tableName.trim();
            Document doc = ExecXML.getDocument(databaseName + ".xml");
            return getActualPosition(doc, tableName, propertyName);
        } catch (Exception ex) {
            return -1;
        }
    }
    /*
     * Hàm này xóa 1 property, nếu property này liên quan tới khóa ngoại, sẽ xóa khóa ngoại đó trước, sau đó xóa property.Xóa thuộc tính đó trong các row để cập nhật
     */

    public static boolean deleteProperty(Document doc, String tableName, String propertyName) {
        boolean result = true;
        if (!ExecPropertyXML.isExistedProperty(doc, tableName, propertyName)) {
            return result = false;
        }
        try {
            doc.getDocumentElement().normalize();
            String[] stridref = null;
            String[] strptref = null;
            //Lấy property có thuộc tính name = propertyName trong table có thuộc tính name = tableName            
            String xPath = "database/table[translate(@name,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='" + tableName.toLowerCase() + "']/property[translate(@name,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='" + propertyName.toLowerCase() + "']";
            Node pt = (Node) ExecXML.execXpath(doc, xPath, "node");
            //Kiểm tra các foreignkey có liên quan để xóa fk đó
            checkedForeignkeyToDelProperty(doc, tableName, propertyName);
            // Tiến hành xóa property
            pt.getParentNode().removeChild(pt);
            // Xóa thuộc tính này ở các row để cập nhật
            ExecRowXML.deleteAttributeOfRow(doc, tableName, propertyName);

            ExecXML.saveXmlFile(doc, ExecTableXML.getNameDatabase(doc) + ".xml");
        } catch (Exception ex) {
            result = false;
        }
        return result;
    }

    public static boolean checkedForeignkeyToDelProperty(Document doc, String tableName, String propertyName) {
        boolean result = true;
        try {
            doc.getDocumentElement().normalize();
            //Lấy các fk trong bảng có thuộc tính name = tableName
            String xPath1 = "database/table[translate(@name,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='" + tableName.toLowerCase() + "']/foreignkey";
            NodeList fkList1 = (NodeList) ExecXML.execXpath(doc, xPath1, "nodeset");
            //Tìm propertyName có trùng với propertyref của foreignkey trong cùng bảng. Có thì xóa fk đó.
            for (int i = 0; i < fkList1.getLength(); i++) {
                Node node = fkList1.item(i);
                Element e = (Element) node;
                String[] str = e.getAttribute("propertyref").toString().split(",");
                for (int j = 0; j < str.length; j++) {
                    if (str[j].equalsIgnoreCase(propertyName)) {
                        Foreignkey fk = new Foreignkey();
                        fk.setPropertyref(e.getAttribute("propertyref"));
                        fk.setTableref(e.getAttribute("tableref"));
                        fk.setIdref(e.getAttribute("idref"));
                        ExecForeignkeyXML.deleteForeignkey(doc, tableName, fk);
                    }
                }
            }
        } catch (Exception ex) {
            result = false;
        }
        return result;
    }
}
